package com.gitee.wsl.mathematics.geometry.d2.triangle

import com.gitee.wsl.io.dataproxy.asProxy
import com.gitee.wsl.mathematics.coordinate.polar.Polar
import com.gitee.wsl.mathematics.coordinate.polar.ext.cartesianF
import com.gitee.wsl.mathematics.geometry.d2.AbstractShape
import com.gitee.wsl.mathematics.geometry.d2.base.Direction
import com.gitee.wsl.mathematics.geometry.d2.contour.ShapeContour
import com.gitee.wsl.mathematics.geometry.d2.line.Line
import com.gitee.wsl.mathematics.vector.vec2.Vec2f
import kotlin.math.PI
import kotlin.math.tan

class Triangle(a: Vec2f, b: Vec2f, c:Vec2f) : AbstractShape(arrayOf(a,b,c).asProxy()),
    TriangleShape2d<Float, Vec2f>{

    override fun createLine(a: Vec2f, b: Vec2f) = Line(a,b)

    override val contour: ShapeContour
        get() = ShapeContour.fromPoints(listOf(a,b, c), closed = true)
    
    companion object{
        /**
         * Creates a triangle from a [centroid] based on the circumradius [radius]
         *
         * @param centroid
         * @param radius
         * @param theta angle of one of the vertices -> equilateral if theta = 60.0 and isosceles otherwise
         * @param rotation
         * @return
         */
        fun fromCentroid(centroid: Vec2f, radius: Double, theta: Double = 60.0, rotation: Double = 0.0): Triangle {
            val omega = (180.0 - theta)

            val x1 = centroid + Polar(rotation, radius).cartesianF
            val x2 = centroid + Polar(omega + rotation, radius).cartesianF
            val x3 = centroid + Polar(-omega + rotation, radius).cartesianF

            val c = (x1 + x2 + x3) / 3.0
            val delta = centroid - c

            return Triangle(x1 + delta, x2 + delta, x3 + delta)
        }

        fun create(baseLine: Float,
                   baseLnCentX: Float,
                   baseLnCentY: Float,
                   direction: Direction = Direction.RIGHT):Triangle {
            // 计算偏移量
            val offset = (baseLine / 2 * tan(60 * PI / 180)).toFloat()
            return when (direction) {
                Direction.UP -> {
                    val p1= Vec2f(baseLnCentX - baseLine / 2, baseLnCentY)
                    val p2= Vec2f(baseLnCentX + baseLine / 2, baseLnCentY)
                    val p3= Vec2f(baseLnCentX, baseLnCentY - offset)
                    Triangle(p1, p2, p3)
                }
                Direction.DOWN -> {
                    val p1= Vec2f(baseLnCentX - baseLine / 2, baseLnCentY)
                    val p2= Vec2f(baseLnCentX + baseLine / 2, baseLnCentY)
                    val p3= Vec2f(baseLnCentX, baseLnCentY + offset)
                    Triangle(p1, p2, p3)
                }
                Direction.LEFT -> {
                    val p1= Vec2f(baseLnCentX, baseLnCentY - baseLine / 2)
                    val p2= Vec2f(baseLnCentX, baseLnCentY + baseLine / 2)
                    val p3= Vec2f(baseLnCentX - offset, baseLnCentY)
                    Triangle(p1, p2, p3)
                }
                Direction.RIGHT -> {
                    val p1= Vec2f(baseLnCentX, baseLnCentY - baseLine / 2)
                    val p2= Vec2f(baseLnCentX, baseLnCentY + baseLine / 2)
                    val p3= Vec2f(baseLnCentX + offset, baseLnCentY)
                    Triangle(p1, p2, p3)
                }
            }
        }

        fun create(width: Float, height: Float,
                   percentLeft: Float = 0f,
                   percentRight: Float = 0f,
                   percentBottom: Float = 0.5f): Triangle {
            val p1= Vec2f(0f, percentLeft * height)
            val p2= Vec2f(percentBottom * width, height)
            val p3= Vec2f(width, percentRight * height)
            return Triangle(p1, p2, p3)
        }
    }
}